package com.tinygray.productConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: tinygray
 * @Description: 公众号:Madison龙少，关注我你会越来越优秀。
 * @className: productConsumer_LockDemo
 * @create: 2021-05-09 15:49
 */

/**
 * 虚假唤醒if while
 *      用if会产生虚假唤醒：说简单点就是if只会判断一次  while会一直判断
 *          因为一个线程可能已经进入if语句里面的时候被阻塞了，这时候其他线程执行完毕，再回来的时候不会再对if条件进行判断，而while会继续判断条件
 */
public class productConsumer_LockDemo {
    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        for (int i = 0; i < 5; i++) {
            new Thread(shareData::increment, "AAA").start();
        }
        for (int i = 0; i < 5; i++) {
            new Thread(shareData::decrement, "BBB").start();
        }

    }
}
//资源类
class ShareData {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //增加
    public void increment() {
        lock.lock();
        try {
            //判断
            while (number != 0) {
                try {
                    //等待
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //干活
            number++;
            System.out.println(Thread.currentThread().getName() + "生产：" + number);
            //通知唤醒
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }
    //减少
    public void decrement() {
        lock.lock();
        try {
            //判断
            while (number == 0) {
                try {
                    //等待
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //干活
            number--;
            System.out.println(Thread.currentThread().getName() + "消费：" + number);
            condition.signalAll();
        }
        catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}
